home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / pfs.c < prev    next >
C/C++ Source or Header  |  1989-09-12  |  23KB  |  770 lines

  1. /* 
  2.  * pfs.c --
  3.  *
  4.  *    The routines in this module set up a call-back interface for
  5.  *    a pseudo-file-system server.  Call-back procedures are called
  6.  *    when client processes do naming operation on the pseudo-file-system.
  7.  *    As a side-effect of the PFS_OPEN operation a pseudo-device connection
  8.  *    can be created for the I/O operations on the object in the
  9.  *    pseudo-file-system.  Pfs_OpenConnection is used to do this, and it
  10.  *    sets of a set of service call-backs for the pseudo-device connenction.
  11.  *    Thus a pseudo-file-system server has a set of naming service
  12.  *    call-backs (typedef Pfs_CallBacks) that are tied to a single
  13.  *    "naming" stream, and another set of I/O service call-backs
  14.  *    (typedef Pdev_CallBacks) for each open file in the pseudo-file-system.
  15.  *
  16.  * Copyright 1989 Regents of the University of California
  17.  * Permission to use, copy, modify, and distribute this
  18.  * software and its documentation for any purpose and without
  19.  * fee is hereby granted, provided that the above copyright
  20.  * notice appear in all copies.  The University of California
  21.  * makes no representations about the suitability of this
  22.  * software for any purpose.  It is provided "as is" without
  23.  * express or implied warranty.
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/pfs.c,v 1.5 89/09/12 14:42:42 brent Exp $ SPRITE (Berkeley)";
  28. #endif not lint
  29.  
  30. #include <stdio.h>
  31. #include <sprite.h>
  32. #include <ctype.h>
  33. #include <errno.h>
  34. #include <pfs.h>
  35. #include <list.h>
  36. #include <status.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/file.h>
  40.  
  41. /*
  42.  * The string below holds an error message if Pfs_Open fails.
  43.  */
  44.  
  45. char pfs_ErrorMsg[150];
  46.  
  47. typedef struct Server {
  48.     unsigned int magic;        /* PFS_MAGIC */
  49.     int streamID;        /* StreamID of naming request-response */
  50.     List_Links connectList;    /* List of all service streams for this
  51.                  * pseudo-filesystem. */
  52.     Pfs_CallBacks *nameService;    /* Naming handlers for pfs operations */
  53.     char *prefix;        /* Pseudo-filesystem prefix */
  54.     Address requestBuf;        /* Naming connection request buffer */
  55.     ClientData clientData;    /* Passed to naming service procedures */
  56. } Server;
  57.  
  58. /*
  59.  * Boolean that can be toggled by applications to get tracing.
  60.  */
  61. int pfs_Trace;
  62.  
  63. static int    PfsNullProc();
  64.  
  65. static Pfs_CallBacks pfsDefaultCallBacks = {
  66.     PfsNullProc,        /* PFS_OPEN */
  67.     PfsNullProc,        /* PFS_GET_ATTR */
  68.     PfsNullProc,        /* PFS_SET_ATTR */
  69.     PfsNullProc,        /* PFS_MAKE_DEVICE */
  70.     PfsNullProc,        /* PFS_MAKE_DIR */
  71.     PfsNullProc,        /* PFS_REMOVE */
  72.     PfsNullProc,        /* PFS_REMOVE_DIR */
  73.     PfsNullProc,        /* PFS_HARD_LINK */
  74.     PfsNullProc,        /* PFS_SYM_LINK */
  75.     PfsNullProc,        /* PFS_DOMAIN_INFO */
  76. };
  77.  
  78. /*
  79.  * PFS_REQUEST_BUF_SIZE     Size of the request buffer for naming stream.
  80.  */
  81.  
  82. #define PFS_REQUEST_BUF_SIZE    (sizeof(Pfs_Request) + sizeof(Fs_2PathData))
  83.  
  84. /*
  85.  * Forward references to procedures in this file:
  86.  */
  87.  
  88. extern void    PfsNamingRequest();
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * Pfs_Open --
  94.  *
  95.  *    Establish a pseudo-filesystem server with a given set of handler
  96.  *    procedures both for the naming operations to the pseudo-filesystem,
  97.  *    and for the I/O operations on pseudo-device connections established
  98.  *    inside the pseudo-filesystem.
  99.  * 
  100.  * Results:
  101.  *    An pointer to a token that contains a clientData field for use
  102.  *    by the caller of Pfs_Open, and the streamID of the naming
  103.  *    request-response stream.  This pointer gets be passed
  104.  *    to Pfs_Close and Pfs_SetHandler.
  105.  *
  106.  * Side effects:
  107.  *    Opens the pseudo-filesystem.  Sets up a call-back.
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. Pfs_Token
  112. Pfs_Open(prefix, rootIDPtr, service, clientData)
  113.     char *prefix;        /* Prefix of the pseudo-filesystem */
  114.     Fs_FileID *rootIDPtr;    /* Server-defined ID of the root */
  115.     Pfs_CallBacks *service;    /* Set of callback procedures.  Can be NULL,
  116.                  * or individual elements can be NULL, to
  117.                  * get default callbacks. */
  118.     ClientData clientData;    /* Passed to naming callbacks */
  119. {
  120.     int namingFD;
  121.     register Server *pfsPtr;
  122.     register int op;
  123.     Pdev_SetBufArgs setBuf;
  124.     int status;
  125.  
  126.     namingFD = open(prefix, O_PFS_MASTER|O_RDONLY, 0);
  127.     if (namingFD < 0) {
  128.     sprintf(pfs_ErrorMsg, "Pfs_Open: \"%s\" service failed, errno %d",
  129.         prefix, errno);
  130.     return((Pfs_Token)NULL);
  131.     }
  132.  
  133.     pfsPtr = (Server *)malloc(sizeof(Server));
  134.     pfsPtr->magic = PFS_MAGIC;
  135.     pfsPtr->streamID = namingFD;
  136.     pfsPtr->clientData = clientData;
  137.  
  138.     List_Init(&pfsPtr->connectList);
  139.  
  140.     pfsPtr->nameService = (Pfs_CallBacks *)malloc(sizeof(Pfs_CallBacks));
  141.     if (service == (Pfs_CallBacks *)NULL) {
  142.     bcopy((Address) &pfsDefaultCallBacks, (Address) pfsPtr->nameService,
  143.             sizeof(Pfs_CallBacks));
  144.     } else {
  145.     bcopy((Address) service, (Address) pfsPtr->nameService,
  146.             sizeof(Pfs_CallBacks));
  147.     }
  148.     if (pfsPtr->nameService->open == (int (*)())NULL) {
  149.     pfsPtr->nameService->open = pfsDefaultCallBacks.open;
  150.     }
  151.     if (pfsPtr->nameService->getAttr == (int (*)())NULL) {
  152.     pfsPtr->nameService->getAttr = pfsDefaultCallBacks.getAttr;
  153.     }
  154.     if (pfsPtr->nameService->setAttr == (int (*)())NULL) {
  155.     pfsPtr->nameService->setAttr = pfsDefaultCallBacks.setAttr;
  156.     }
  157.     if (pfsPtr->nameService->makeDevice == (int (*)())NULL) {
  158.     pfsPtr->nameService->makeDevice = pfsDefaultCallBacks.makeDevice;
  159.     }
  160.     if (pfsPtr->nameService->makeDir == (int (*)())NULL) {
  161.     pfsPtr->nameService->makeDir = pfsDefaultCallBacks.makeDir;
  162.     }
  163.     if (pfsPtr->nameService->remove == (int (*)())NULL) {
  164.     pfsPtr->nameService->remove = pfsDefaultCallBacks.remove;
  165.     }
  166.     if (pfsPtr->nameService->removeDir == (int (*)())NULL) {
  167.     pfsPtr->nameService->removeDir = pfsDefaultCallBacks.removeDir;
  168.     }
  169.     if (pfsPtr->nameService->rename == (int (*)())NULL) {
  170.     pfsPtr->nameService->rename = pfsDefaultCallBacks.rename;
  171.     }
  172.     if (pfsPtr->nameService->hardLink == (int (*)())NULL) {
  173.     pfsPtr->nameService->hardLink = pfsDefaultCallBacks.hardLink;
  174.     }
  175.     if (pfsPtr->nameService->symLink == (int (*)())NULL) {
  176.     pfsPtr->nameService->symLink = pfsDefaultCallBacks.symLink;
  177.     }
  178.     if (pfsPtr->nameService->domainInfo == (int (*)())NULL) {
  179.     pfsPtr->nameService->domainInfo = pfsDefaultCallBacks.domainInfo;
  180.     }
  181.  
  182.     pfsPtr->prefix = prefix;
  183.     pfsPtr->requestBuf = (Address)malloc(PFS_REQUEST_BUF_SIZE);
  184.     setBuf.requestBufAddr = pfsPtr->requestBuf;
  185.     setBuf.requestBufSize = PFS_REQUEST_BUF_SIZE;
  186.     setBuf.readBufAddr = NULL;
  187.     setBuf.readBufSize = 0;
  188.     status = Fs_IOControl(namingFD, IOC_PDEV_SET_BUF, sizeof(Pdev_SetBufArgs),
  189.         (Address)&setBuf, 0, (Address) NULL);
  190.     if (status != SUCCESS) {
  191.     sprintf(pfs_ErrorMsg, "IOC_PDEV_SET_BUF failed <%x>\n", status);
  192.     close(namingFD);
  193.     return((Pfs_Token)NULL);
  194.     }
  195.     (void)Fs_IOControl(namingFD, IOC_PFS_SET_ID, sizeof(Fs_FileID),
  196.         (Address)rootIDPtr, 0, (Address) NULL);
  197.  
  198.     Fs_EventHandlerCreate(namingFD, FS_READABLE, PfsNamingRequest,
  199.                 (ClientData)pfsPtr);
  200.  
  201.     return((Pfs_Token)pfsPtr);
  202. }
  203.  
  204. /*
  205.  *----------------------------------------------------------------------
  206.  *
  207.  * Pfs_SetHandler --
  208.  *
  209.  *    Set a handler for a particular PFS request.  If the handler is
  210.  *    NULL then a default procedure replaces the existing handler.
  211.  * 
  212.  * Results:
  213.  *    None.
  214.  *
  215.  * Side effects:
  216.  *    Updates the top-level callback list, the one used for naming requests.
  217.  *
  218.  *----------------------------------------------------------------------
  219.  */
  220. int (*
  221. Pfs_SetHandler(pfsToken, operation, handler))()
  222.     Pfs_Token pfsToken;        /* Return value from Pfs_Open */
  223.     int operation;        /* Which operation to set the handler for */
  224.     int (*handler)();        /* The callback procedure */
  225. {
  226.     register Server *pfsPtr = (Server *)pfsToken;
  227.     register Pfs_CallBacks *service = pfsPtr->nameService;
  228.     int (*oldHandler)();
  229.  
  230.     if (pfsPtr->magic != PFS_MAGIC) {
  231.     fprintf(stderr, "Bad token passed to Pfs_SetHandler\n");
  232.     return NULL;
  233.     }
  234.     switch (operation) {
  235.     case PFS_OPEN:
  236.         oldHandler = service->open;
  237.         if (handler == (int (*)())NULL) {
  238.         service->open = PfsNullProc;
  239.         } else {
  240.         service->open = handler;
  241.         }
  242.         break;
  243.     case PFS_GET_ATTR:
  244.         oldHandler = service->getAttr;
  245.         if (handler == (int (*)())NULL) {
  246.         service->getAttr = PfsNullProc;
  247.         } else {
  248.         service->getAttr = handler;
  249.         }
  250.         break;
  251.     case PFS_SET_ATTR:
  252.         oldHandler = service->setAttr;
  253.         if (handler == (int (*)())NULL) {
  254.         service->setAttr = PfsNullProc;
  255.         } else {
  256.         service->setAttr = handler;
  257.         }
  258.         break;
  259.     case PFS_MAKE_DEVICE:
  260.         oldHandler = service->makeDevice;
  261.         if (handler == (int (*)())NULL) {
  262.         service->makeDevice = PfsNullProc;
  263.         } else {
  264.         service->makeDevice = handler;
  265.         }
  266.         break;
  267.     case PFS_MAKE_DIR:
  268.         oldHandler = service->makeDir;
  269.         if (handler == (int (*)())NULL) {
  270.         service->makeDir = PfsNullProc;
  271.         } else {
  272.         service->makeDir = handler;
  273.         }
  274.         break;
  275.     case PFS_REMOVE:
  276.         oldHandler = service->remove;
  277.         if (handler == (int (*)())NULL) {
  278.         service->remove = PfsNullProc;
  279.         } else {
  280.         service->remove = handler;
  281.         }
  282.         break;
  283.     case PFS_REMOVE_DIR:
  284.         oldHandler = service->removeDir;
  285.         if (handler == (int (*)())NULL) {
  286.         service->removeDir = PfsNullProc;
  287.         } else {
  288.         service->removeDir = handler;
  289.         }
  290.         break;
  291.     case PFS_RENAME:
  292.         oldHandler = service->rename;
  293.         if (handler == (int (*)())NULL) {
  294.         service->rename = PfsNullProc;
  295.         } else {
  296.         service->rename = handler;
  297.         }
  298.         break;
  299.     case PFS_HARD_LINK:
  300.         oldHandler = service->hardLink;
  301.         if (handler == (int (*)())NULL) {
  302.         service->hardLink = PfsNullProc;
  303.         } else {
  304.         service->hardLink = handler;
  305.         }
  306.         break;
  307.     case PFS_SYM_LINK:
  308.         oldHandler = service->symLink;
  309.         if (handler == (int (*)())NULL) {
  310.         service->symLink = PfsNullProc;
  311.         } else {
  312.         service->symLink = handler;
  313.         }
  314.         break;
  315.     case PFS_DOMAIN_INFO:
  316.         oldHandler = service->domainInfo;
  317.         if (handler == (int (*)())NULL) {
  318.         service->domainInfo = PfsNullProc;
  319.         } else {
  320.         service->domainInfo = handler;
  321.         }
  322.         break;
  323.     default:
  324.         fprintf(stderr, "Bad operation passed to Pfs_SetHandler");
  325.         oldHandler = NULL;
  326.         break;
  327.     }
  328.     return oldHandler;
  329. }
  330.  
  331. /*
  332.  *----------------------------------------------------------------------
  333.  *
  334.  * PfsNamingRequest --
  335.  *
  336.  *    Called when the naming request-response stream has a new request.
  337.  *    This makes a call-back to the corresponding procedure in the
  338.  *    nameService list for the pseudo-filesystem.
  339.  * 
  340.  * Results:
  341.  *    None.
  342.  *
  343.  * Side effects:
  344.  *    Calls the user's handler for the naming operation.
  345.  *
  346.  *----------------------------------------------------------------------
  347.  */
  348. /*ARGSUSED*/
  349. void
  350. PfsNamingRequest(clientData, streamID, eventMask)
  351.     ClientData clientData;
  352.     int streamID;
  353.     int eventMask;
  354. {
  355.     register Server *pfsPtr = (Server *)clientData;
  356.     Pdev_BufPtrs bufPtrs;
  357.     Pfs_Request *requestPtr;
  358.     Pdev_Reply reply;
  359.     int numBytes;
  360.     Address dataPtr;
  361.     int status;
  362.     int replySize;
  363.     Address replyBuf;
  364.     Fs_Attributes attr;
  365.     Fs_DomainInfo domainInfo;
  366.     Fs_RedirectInfo redirectInfo;
  367.     Fs_2PathRedirectInfo redirect2Info;
  368.  
  369.     if (pfs_Trace) {
  370.     fprintf(stderr, "<%s> ", pfsPtr->prefix);
  371.     }
  372.     /*
  373.      * Read the current pointers for the request buffer.
  374.      */
  375.  
  376.     numBytes = read(streamID, (char *) &bufPtrs, sizeof(Pdev_BufPtrs));
  377.     if (numBytes != sizeof(Pdev_BufPtrs)) {
  378.     panic("%s; status \"%s\", count %d",
  379.         "PfsNamingRequest had trouble reading request buffer pointers",
  380.         strerror(errno), numBytes);
  381.     }
  382.     if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  383.     panic("%s: %d", "PfsNamingRequest got bad pointer magic number",
  384.         bufPtrs.magic);
  385.     }
  386.     /*
  387.      * While there are still requests in the buffer, service them.
  388.      */
  389.     while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  390.     requestPtr =
  391.         (Pfs_Request *)&pfsPtr->requestBuf[bufPtrs.requestFirstByte];
  392.     if (requestPtr->hdr.magic != PFS_REQUEST_MAGIC) {
  393.         printf("PfsNamingRequest, bad request magic # 0x%x\n",
  394.                 requestPtr->hdr.magic);
  395.         bufPtrs.requestFirstByte = bufPtrs.requestLastByte + 1;
  396.     }
  397.     dataPtr = (Address)((int)requestPtr + sizeof(Pfs_Request));
  398.  
  399.     status = FS_FILE_NOT_FOUND;
  400.     replySize = 0;
  401.     replyBuf = NULL;
  402.     switch (requestPtr->hdr.operation) {
  403.         case PFS_OPEN: {
  404.         register char *name;
  405.         Fs_OpenArgs *openArgsPtr;
  406.  
  407.         name = (char *)dataPtr;
  408.         openArgsPtr = &requestPtr->param.open;
  409.         if (pfs_Trace) {
  410.             fprintf(stderr, "OPEN %s: uid %d gid %d use %x cwd <%d,%d,%x,%x>",
  411.             name, openArgsPtr->id.user, openArgsPtr->id.group[0],
  412.             openArgsPtr->useFlags,
  413.             openArgsPtr->prefixID.serverID,
  414.             openArgsPtr->prefixID.type, openArgsPtr->prefixID.major,
  415.             openArgsPtr->prefixID.minor);
  416.         }
  417.         status = (*pfsPtr->nameService->open)(pfsPtr->clientData,
  418.                 name, openArgsPtr, &redirectInfo);
  419.         if (status == SUCCESS) {
  420.             /*
  421.              * The openProc has already replied.
  422.              */
  423.             if (pfs_Trace) {
  424.             fprintf(stderr, " Returns OK\n");
  425.             }
  426.             goto nextMsg;
  427.         }
  428.         break;
  429.         }
  430.         case PFS_GET_ATTR: {
  431.         register char *name;
  432.  
  433.         name = (char *)dataPtr;
  434.  
  435.         if (pfs_Trace) {
  436.             fprintf(stderr, "GET_ATTR %s", name);
  437.         }
  438.         status = (*pfsPtr->nameService->getAttr)
  439.             (pfsPtr->clientData, name, &requestPtr->param.getAttr,
  440.             &attr, &redirectInfo);
  441.         if (status == SUCCESS) {
  442.             replyBuf = (Address)&attr;
  443.             replySize = sizeof(Fs_Attributes);
  444.         }
  445.         break;
  446.         }
  447.         case PFS_SET_ATTR: {
  448.         register Pfs_SetAttrData *setAttrPtr =
  449.             (Pfs_SetAttrData *)dataPtr;
  450.  
  451.         if (pfs_Trace) {
  452.             fprintf(stderr, "SET_ATTR %s: ", setAttrPtr->name);
  453.             fprintf(stderr, "client %d uid %d gid %d: ",
  454.             requestPtr->param.open.clientID,
  455.             requestPtr->param.open.id.user,
  456.             requestPtr->param.open.id.group[0]);
  457.             if (setAttrPtr->flags & FS_SET_TIMES) {
  458.             fprintf(stderr, "(access = %d) (modify = %d) ",
  459.                 setAttrPtr->attr.accessTime.seconds,
  460.                 setAttrPtr->attr.dataModifyTime.seconds);
  461.             }
  462.             if (setAttrPtr->flags & FS_SET_MODE) {
  463.             fprintf(stderr, "(mode = 0%o) ", setAttrPtr->attr.permissions);
  464.             }
  465.             if (setAttrPtr->flags & FS_SET_OWNER) {
  466.             fprintf(stderr, "(uid = %d) (gid = %d) ", setAttrPtr->attr.uid,
  467.                     setAttrPtr->attr.gid);
  468.             }
  469.             if (setAttrPtr->flags & FS_SET_FILE_TYPE) {
  470.             fprintf(stderr, "(userType = %d) ", setAttrPtr->attr.userType);
  471.             }
  472.             if (setAttrPtr->flags & FS_SET_DEVICE) {
  473.             fprintf(stderr, "(device = <%d,%d,%d>) ",
  474.                 setAttrPtr->attr.devServerID,
  475.                 setAttrPtr->attr.devType,
  476.                 setAttrPtr->attr.devUnit);
  477.             }
  478.         }
  479.         status = (*pfsPtr->nameService->setAttr)
  480.             (pfsPtr->clientData, setAttrPtr->name,
  481.              &requestPtr->param.setAttr, setAttrPtr->flags,
  482.              &setAttrPtr->attr, &redirectInfo);
  483.         break;
  484.         }
  485.         case PFS_MAKE_DEVICE: {
  486.         register char *name;
  487.  
  488.         name = (char *)dataPtr;
  489.         if (pfs_Trace) {
  490.             fprintf(stderr, "MAKE_DEVICE %s: <%d,%d,%d>", name,
  491.             requestPtr->param.makeDevice.device.serverID,
  492.             requestPtr->param.makeDevice.device.type,
  493.             requestPtr->param.makeDevice.device.unit);
  494.         }
  495.         status = (*pfsPtr->nameService->makeDevice)
  496.             (pfsPtr->clientData, name, &requestPtr->param.makeDevice,
  497.             &redirectInfo);
  498.         break;
  499.         }
  500.         case PFS_MAKE_DIR: {
  501.         register char *name;
  502.  
  503.         name = (char *)dataPtr; 
  504.         if (pfs_Trace) {
  505.             fprintf(stderr, "MAKE_DIR %s", name);
  506.         }
  507.         status = (*pfsPtr->nameService->makeDir)
  508.             (pfsPtr->clientData, name, &requestPtr->param.makeDir,
  509.             &redirectInfo);
  510.         break;
  511.         }
  512.         case PFS_REMOVE: {
  513.         register char *name;
  514.  
  515.         name = (char *)dataPtr;
  516.         if (pfs_Trace) {
  517.             fprintf(stderr, "REMOVE %s", name);
  518.         }
  519.         status = (*pfsPtr->nameService->remove)
  520.             (pfsPtr->clientData, name, &requestPtr->param.remove,
  521.             &redirectInfo);
  522.         break;
  523.         }
  524.         case PFS_REMOVE_DIR: {
  525.         register char *name;
  526.  
  527.         name = (char *)dataPtr;
  528.         if (pfs_Trace) {
  529.             fprintf(stderr, "REMOVE %s", name);
  530.         }
  531.         status = (*pfsPtr->nameService->removeDir)
  532.             (pfsPtr->clientData, name, &requestPtr->param.removeDir,
  533.             &redirectInfo);
  534.         break;
  535.         }
  536.         case PFS_RENAME: {
  537.         register Fs_2PathData *pathsPtr;
  538.  
  539.         pathsPtr = (Fs_2PathData *)dataPtr;
  540.         if (pfs_Trace) {
  541.             fprintf(stderr, "PFS_RENAME %s %s", 
  542.             pathsPtr->path1, pathsPtr->path2);
  543.         }
  544.         status = (*pfsPtr->nameService->rename)
  545.             (pfsPtr->clientData, pathsPtr->path1, pathsPtr->path2,
  546.             &requestPtr->param.rename, &redirect2Info);
  547.         break;
  548.         }
  549.         case PFS_HARD_LINK: {
  550.         register Fs_2PathData *pathsPtr;
  551.  
  552.         pathsPtr = (Fs_2PathData *)dataPtr;
  553.         if (pfs_Trace) {
  554.             fprintf(stderr, "PFS_HARD_LINK %s %s", 
  555.             pathsPtr->path1, pathsPtr->path2);
  556.         }
  557.         status = (*pfsPtr->nameService->hardLink)
  558.             (pfsPtr->clientData, pathsPtr->path1, pathsPtr->path2,
  559.             &requestPtr->param.hardLink, &redirect2Info);
  560.         break;
  561.         }
  562.         case PFS_SYM_LINK: {
  563.         register Fs_2PathData *pathsPtr;
  564.  
  565.         pathsPtr = (Fs_2PathData *)dataPtr;
  566.         if (pfs_Trace) {
  567.             fprintf(stderr, "PFS_SYM_LINK %s %s", 
  568.             pathsPtr->path1, pathsPtr->path2);
  569.         }
  570.         status = (*pfsPtr->nameService->symLink)
  571.             (pfsPtr->clientData, pathsPtr->path1, pathsPtr->path2,
  572.             &requestPtr->param.symLink, &redirectInfo);
  573.         break;
  574.         }
  575.         case PFS_DOMAIN_INFO: {
  576.         if (pfs_Trace) {
  577.             fprintf(stderr, "PFS_DOMAIN_INFO");
  578.         }
  579.         status = (*pfsPtr->nameService->domainInfo)
  580.             (pfsPtr->clientData, &requestPtr->param.domainInfo,
  581.             &domainInfo);
  582.         replyBuf = (Address)&domainInfo;
  583.         replySize = sizeof(domainInfo);
  584.         break;
  585.         }
  586.         default:
  587.         panic("PfsNamingRequest: bad request on request stream: %d",
  588.             requestPtr->hdr.operation);
  589.     }
  590.     if (status == EREMOTE || status == FS_LOOKUP_REDIRECT) {
  591.         status = FS_LOOKUP_REDIRECT;
  592.         if (requestPtr->hdr.operation == PFS_RENAME ||
  593.         requestPtr->hdr.operation == PFS_HARD_LINK) {
  594.         replyBuf = (Address)&redirect2Info;
  595.         replySize = sizeof(Fs_2PathRedirectInfo);
  596.         } else {
  597.         replyBuf = (Address)&redirectInfo;
  598.         replySize = sizeof(Fs_RedirectInfo);
  599.         }
  600.     }
  601.     if (pfs_Trace) {
  602.         fprintf(stderr, " Returns %x\n", status);
  603.     }
  604.     reply.magic = PDEV_REPLY_MAGIC;
  605.     reply.status = status;
  606.     reply.replyBuf = replyBuf;
  607.     reply.replySize = replySize;
  608.     reply.selectBits = 0;
  609.     reply.signal = 0;
  610.     reply.code = 0;
  611.     status = Fs_IOControl(streamID, IOC_PDEV_REPLY,
  612.         sizeof(Pdev_Reply), (Address) &reply, 0, (Address) NULL);
  613.     if (status != SUCCESS) {
  614.         fprintf(stderr, "IOC_PDEV_REPLY status 0x%x\n", status);
  615.     }
  616.     /*
  617.      * Check the next message.
  618.      */
  619. nextMsg:
  620.     bufPtrs.requestFirstByte += requestPtr->hdr.messageSize;
  621.     }
  622.     /*
  623.      * Tell the kernel we've processed the messages.
  624.      */
  625.     (void)Fs_IOControl(streamID, IOC_PDEV_SET_PTRS,
  626.             sizeof(Pdev_BufPtrs), (Address)&bufPtrs,
  627.             0, (Address) NULL);
  628. }
  629.  
  630. /*
  631.  *----------------------------------------------------------------------
  632.  *
  633.  * Pfs_OpenConnection --
  634.  *
  635.  *    Called to open a new pdev connection in response to an PFS_OPEN
  636.  *    request.  This does an IOC_PFS_OPEN to set up the connection, and
  637.  *    the sets up a call-back to PdevServiceRequest to handle the subsequent
  638.  *    operations on the new connection.  The pdev handlers are the
  639.  *    default ones until updated with Pdev_SetupHandler.
  640.  * 
  641.  * Results:
  642.  *    None.
  643.  *
  644.  * Side effects:
  645.  *    Turns off tracing, etc.
  646.  *
  647.  *----------------------------------------------------------------------
  648.  */
  649. Pdev_Stream *
  650. Pfs_OpenConnection(token, fileIDPtr, reqBufSize, readBufSize, readBuf, selectBits, service)
  651.     Pfs_Token token;        /* Ref. to pseudo-file-system state */
  652.     Fs_FileID *fileIDPtr;    /* Server's name for this conection */
  653.     int reqBufSize;        /* Preferred size for request buffer */
  654.     int readBufSize;        /* Size for optional read buffer, 0 means
  655.                  * no read buffer */
  656.     char *readBuf;        /* The read buffer itself, or NULL */
  657.     int selectBits;        /* Initial select state of the connection */
  658.     Pdev_CallBacks *service;    /* Set of handlers for this pdev connection */
  659. {
  660.     int newStreamID;
  661.     register Server *pfsPtr = (Server *)token;
  662.     Pdev_SetBufArgs setBuf;
  663.     int status;
  664.  
  665.     if (pfsPtr->magic != PFS_MAGIC) {
  666.     fprintf(stderr, "Pfs_OpenConnection got bad token\n");
  667.     return NULL;
  668.     }
  669.     status = Fs_IOControl(pfsPtr->streamID, IOC_PFS_OPEN, sizeof(Fs_FileID),
  670.         fileIDPtr, sizeof(int), (Address)&newStreamID);
  671.     if (status != SUCCESS) {
  672.     fprintf(stderr, "IOC_PFS_OPEN failed <%x>\n", status);
  673.     return NULL;
  674.     }
  675.     /*
  676.      * Set up state for the new pseudo-device connection
  677.      */
  678.     return (PdevSetup(newStreamID, (Address)pfsPtr, &pfsPtr->connectList,
  679.         reqBufSize, readBufSize, readBuf, service, selectBits));
  680.  
  681. }
  682.  
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * Pfs_PassFile --
  687.  *
  688.  *    Pass off an open file in response to an open request by a client.
  689.  *    This takes a regular open file descriptor and passes it into the
  690.  *    kernel in response to an open request by a client.  This should
  691.  *    only be called from the open call-back service procedure.
  692.  *
  693.  * Results:
  694.  *    An error code.
  695.  *
  696.  * Side effects:
  697.  *    Completes a PFS_OPEN transaction by making the IOC_PFS_PASS_STREAM
  698.  *    ioctl to pass off the open file descriptor.
  699.  *
  700.  *----------------------------------------------------------------------
  701.  */
  702. int
  703. Pfs_PassFile(pfsToken, streamID)
  704.     Pfs_Token pfsToken;
  705.     int streamID;
  706. {
  707.     register Server *pfsPtr = (Server *)pfsToken;
  708.     register int status;
  709.  
  710.     if (pfsPtr->magic != PFS_MAGIC) {
  711.     fprintf(stderr, "Pfs_PassFile got bad token\n");
  712.     return EINVAL;
  713.     }
  714.     status = Fs_IOControl(pfsPtr->streamID, IOC_PFS_PASS_STREAM, sizeof(int),
  715.         &streamID, 0, NULL);
  716.     return status;
  717. }
  718.  
  719. /*
  720.  *----------------------------------------------------------------------
  721.  *
  722.  * Pfs_Close --
  723.  *
  724.  *    Stop pseudo-file-system service.
  725.  *
  726.  * Results:
  727.  *    None.
  728.  *
  729.  * Side effects:
  730.  *    Closes the naming request-response stream and free's up alloc'd memory.
  731.  *
  732.  *----------------------------------------------------------------------
  733.  */
  734. void
  735. Pfs_Close(pfsToken)
  736.     Pfs_Token pfsToken;
  737. {
  738.     register Server *pfsPtr = (Server *)pfsToken;
  739.  
  740.     if (pfsPtr->magic != PFS_MAGIC) {
  741.     fprintf(stderr, "Pfs_Close got bad token\n");
  742.     return;
  743.     }
  744.     (void)close(pfsPtr->streamID);
  745.     (void)free((char *)pfsPtr->nameService);
  746.     (void)free((char *)pfsPtr->requestBuf);
  747.     (void)free((char *)pfsPtr);
  748. }
  749.  
  750. /*
  751.  *----------------------------------------------------------------------
  752.  *
  753.  * PfsNullProc --
  754.  *
  755.  *    Do-nothing callback.
  756.  *
  757.  * Results:
  758.  *    Returns FS_FILE_NOT_FOUND.
  759.  *
  760.  * Side effects:
  761.  *    None.
  762.  *
  763.  *----------------------------------------------------------------------
  764.  */
  765. static int
  766. PfsNullProc()
  767. {
  768.     return(FS_FILE_NOT_FOUND);
  769. }
  770.